const WebSocket = require('ws')
const http = require('http')
const ywsUtils = require('./utils')
const url = require("url");
const setupWSConnection = ywsUtils.setupWSConnection
const docs = ywsUtils.docs
const crypto = require('crypto')
const port = parseInt(process.env.PORT) || 5700
const SALT = process.env.salt || ''
const CENTER_HOST = process.env.CENTER_HOST || ''
const CENTER_PORT = process.env.CENTER_PORT || 0
const PERMISSION_PATH = process.env.PERMISSION_PATH || ''
const COLLABORATION_PATH = process.env.COLLABORATION_PATH || ''
/**
 *
 * @param request {IncomingMessage} [request]
 * @param response {ServerResponse}[response]
 */
const handleCallback = (request, response) => {
    const options = {
        hostname: CENTER_HOST,
        port: CENTER_PORT,
        path: COLLABORATION_PATH,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    };
    let bodyStr = '';
    // 监听数据片段
    request.on('data', (chunk) => {
        bodyStr += chunk.toString(); // 将接收到的Buffer转换为字符串，并追加到body
    });

    // 当没有更多的数据要接收时，执行
    request.on('end', () => {
        // 此时body包含了整个请求体

        // 响应客户端
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.end('Request body received\n');
        const body = JSON.parse(bodyStr);
        const room = body["room"];
        const content = body["data"]["slate"]["content"];
        const hash = crypto.createHash('sha256');
        hash.update(SALT + "room_" + room + "content_" + content);
        const signature = hash.digest('hex');

        const postData = {
            "room": room,
            "content": content,
            "signature": signature
        }
        const req = http.request(options, (res) => {

        });
        req.write(JSON.stringify(postData))
        req.end();
    });

}
/**
 *
 * @param request {IncomingMessage} [request]
 * @param response {ServerResponse}[response]
 */
const handleRoomClose = (request, response) => {
    const header = request.headers
    const room = header["room"];
    const timestamp = header["timestamp"];
    const signature = header["signature"];
    if (room == null || timestamp == null || signature == null) {
        return;
    }
    if (Date.now() - 10000 > Number.parseInt(timestamp)) {
        return;
    }
    const hash = crypto.createHash('sha256');
    hash.update(SALT + "room_" + room + "timeStamp_" + timestamp);
    const generatedSignature = hash.digest('hex');
    if (signature !== generatedSignature) {
        return;
    }
    docs.delete(room)

    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.end('Request body received\n');

}

const server = http.createServer((request, response) => {
    try {
        if (request.url === "/article/update") {
            handleCallback(request, response)
        }
        if (request.url === "/room/close") {
            handleRoomClose(request, response)
        }
    } catch (e) {
        console.log(e)
    }
})


const wss = new WebSocket.Server({server})
wss.on('connection', (conn, request) => {
    const searchParams = url.parse(request.url, true).query

    const articleId = searchParams.articleId
    const sessionId = searchParams.JSESSIONID
    if (!articleId || !sessionId) {
        return;
    }
    const postData = JSON.stringify({
        'sessionId': sessionId,
        'articleId': articleId
    });
    const options = {
        hostname: CENTER_HOST,
        port: CENTER_PORT,
        path: PERMISSION_PATH,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    };
    let data = '';
    try {
        const req = http.request(options, (res) => {

            res.on('data', (chunk) => {
                data += chunk.toString()
            })
            res.on('end', (chunk) => {
                const permission = JSON.parse(data)
                if (!permission.data) {
                    return;
                }
                setupWSConnection(conn, request, {gc: request.url.slice(1) !== 'ws/prosemirror-versions'})
            })

        });
        req.write(postData)
        req.end();
    } catch (err) {
        console.log(err)
    }

})
server.listen(port, '0.0.0.0')
